\documentclass[12pt]{article}
\usepackage{times}
\usepackage{graphicx}
\usepackage{sidecap}
\usepackage{wrapfig}
\usepackage{fancyhdr}
\usepackage{amsmath}
\pagestyle{fancy}
\renewcommand{\baselinestretch}{1.2}
\newenvironment{mylisting}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\newenvironment{mylisting2}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\newenvironment{mylisting3}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\newenvironment{mylisting4}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\newenvironment{mylisting5}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}
\newenvironment{mylisting6}
{\begin{list}{}{\setlength{\leftmargin}{1em}}\item\scriptsize\bfseries}
{\end{list}}

%%% This file is Open Content - bubble

%%% FIXME GPU with elem particles

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CHECK THE FIXMES%%%%%%%%%%%%%%%%%%%%%%%%5

\begin{document}
	\textbf{{\Huge Java 3D engine}}
{\center{Dec 17, 2012, 
	Johan Ceuppens, Theo D'Hondt - Vrije Universiteit Brussel}}
\\
{\large{\textbf{\center Abstract}}}
\\
\\

	This file contains a discussion of research on Quaternion 3D information
	With group and algebra theory we will try to construct a basis for
	further research on "neat" transformations. There is Java or Scheme
	code for all problems discussed.\\	


\section{\large Introduction}

This file contains 3D research conducted on a Java 3D codebase using java.awt.X
for graphics (see Appendix for code) and contains topics for using e.g. 2D 
algorithms for use in a 3D vector space (read: 3D engine.) 

The first part goes on about Vector space and group and algebra theory for 
speeding up the engine. Clifford algebras come to mind and generate faster
algorithms on Quaternion and Euler engine parts.
The second part is about Matrix theory (e.g. Pauli Matrices) for use on the
Java engine.

\section{\large Vector Spaces, group algebras and Quaternions}
\subsection{\large Basics }
For using integers in an int[] for each vertex, a Fraction class can be added
per vertex group or vertex so that there are floating point vertices.
OpenGL works this way by using floats for x,y,z coordinates. As the engine 
uses Java's AWT for portability, it has a draw method which only uses an x and 
an y integer. The Hamilton complex property is a non degenerate quadratic form
consisting of the fundamental Clifford identity ${e}_{i}{e}_{j} = -{e}_{j}{e}_{i}$. In Quaternion systems this becomes $Q(v) = {w}^2+{x}^2+{y}^2+{z}^2$ where 
the standard dim(V) = 4 and V a complex vector space. 

The Clifford algebra Cl(V,Q) produces a graded algebra with Tensor algebra T(V)
where ${F}^{0} \subset {F}^{1} \subset ... \subset {F}^{k}$ contains sums of tensors with $rank <= k$.
${Gr}_{F}Cl(V,Q) = {\bigoplus}_{k} \frac{{F}^{k}}{{F}^{k-1}}$.%FIXME write out calcs
%FIXME multiplicative groups as F or not ?

Algebras who get combined with + or x can be defined using combinations of 
operandi and operator coexistence e.g. a modulus 4 group can be combined with 
a modulus 3 group by combining the moduli together with the elements of 
the group. The graded algebra above has an extension as a Riemannian manifold
by a rank descent of 1 per tensor algebra which is a combination allieviated
through a differential manifold and a, an sich, an intergrated manifold or
vector fields : $p -> {g}_{p}(X(p),Y(p))$ is a smooth function where the tangent
space varies point for point on the smooth Riemannian manifold (M.) 
The family ${g}_{p}$ of inner products is the metric, a Riemannian tensor of
algebraic equivalence. An inner product on itself is a metric of a Clifford
algebra where $d(v,w) = {v}_{1}{w}_{1}+{v}_{2}{w}_{2}+{v}_{3}{w}_{3}$ is a 
Euclidean metric derived of the Quadratic form Q of vector space V.
This measures in $R^{4}$ onto the ${R}^{3}$ hyperplane.

A graded algebra has the following precursions : 
$A = {\bigoplus}_{n \in N}{A}_{n} = {A}_{0} \oplus {A}_{1} \oplus {A}_{2} \oplus ...$ where A is a graded ring
consisting of the direct sum of abelian additive groups.
An algebra A over a ring R is a graded algebra if it is graded as a ring. 
In this case we require : ${A}_{i}{R}_{j} \subseteq {A}_{i+j}$ and
${R}_{i}{A}_{j} \subseteq {A}_{i+j}$.

The graded (CLifford) algebra is written out as a Tensor sum of rank n 
and rank n-1 where n is the dimension of vector space V, Cl(V,Q) the Clifford
algebra, Q the quadratic norm. 
Note that Q can be different from the quadratic norm and in changing Q we get
different magnitudes through which quaternions can rotate. The following Java
code defines this rotation : 

\begin{mylisting4}
\begin{verbatim}
//axis is a unit vector and float s is a local rotation.
public Quaternion rotate(float angle, float xaxisx, float yaxisy, float zaxisz)
{
	float s = (float)Math.sin(angle/2);
	//quaternion = w+x+y+z
	return new Quaternion((float)Math.cos(angle/2),xaxisx*s,
						yaxisy*s,
						zaxisz*s);	

}

\end{verbatim}
\end{mylisting4}

Further on we will discuss the properties of the non-quadratic norm Q for
improving the graded algebra with tensor interpolation and calculation as 
described in the definitions of the Clifford graded algebra and commuting
Tensor algebras. 

A tensor can be seen as a norm on its own with basis vectors ${e}_{i}$ you
get a transformation of this basis to ${e'}_{i} = {\Sigma}_{j}{R}_{i}^{j}{e}_{j} = {R}^{j}_{i}{e}_{j}$

More on tensors and matrices in the next sections.

The tensor algebra T(V) over a vector space V and a field K is 
$T(V)={\bigoplus}^{\infty}_{k=0}{T}^{k}V = K \oplus V \oplus (V \otimes V))
\oplus (V \otimes V \otimes V) \oplus ...$.
%Tensor products are not biassociative but left or right handed, as a covector.

%FIXME following section : complex tensors, spinors in Clifford algebra tensors and multidimensional arrays
%FIXME Hamiltonian to tensor product

Vector fields can be described by Hamiltonian mechanics. The Hamiltonian
describes the energy of this system. The flow on a Riemannian manifold is an
example of a vector field.
The Hamilton-Jacobi matrix can be used to search for extrema in e.g. a 
time and space dependent way on the Riemannian manifold. The kinetic energy
and tensor direction define the interpolation with this mechanical aspect. The
fields can be complex, real or quantum fields. A Riemannian metric (tensor)
can give us geometric information about angles, lengths, volumes, areas, 
curvature, gradients, divergence etc. Any Riemannian manifold has a Riemannian
metric : $g = {\Sigma}_{ij}{g}_{ij}{dx}^{i} \otimes d{x}^{j}$ with $\otimes$
the tensor product. The tensors interpolate by twisting the tensor, it does 
work, as a force field. Through quaternion algebra there is no 'Gimbal lock', 
which means that there is always a roll, yaw and pitch value even on a Mobius
strip.

Gradients and divergences can be found with differential equations for example
on a volume or area. The Kinetic energy of such vector fields can be described
by the Riemannian manifold's metric tensor analog to the inner product, as a 
(time) series $T = {\Sigma}\frac{1}{2}{m}_{i}{x}_{i}^{2}$. The inner product
defines the amount of work the tensor equates. An electro-magnetic tensor
gives work related to the change in flux of its magnetic field (Maxwell's laws.)

The Quaternion group ${Q}_{8}$ can be extended by cross-referencing operators
and operandi in aspect to combining with other groups. The Riemannian manifold
has a inner product in its metric where the graded Clifford algebra is a 
$\otimes$ combination of Tensor algebras (see above for the formula.)

%FIXME calculation of tensor algebra <-> graded Clifford algebra
By applying a Hamiltonian function on a Quaternion we can derive the energy
and changes in the Quaternion's rotation. The Hamiltonian of a Quaternion  
gives us changes through time and space of the phases (angles) and position
of the 3 dimensional coordinate vector inside the quaternion. We derive now
that the quaternion obeys the Electro-Magnetic tensor as described in the
Maxwell-Lorentz equation. The norm of the Quaternion Clifford algebra has an
analogy with quaternion's rotation matrix's kinetic energy, which is the 
Hamiltonian itself. The norm is a positive definite magnitude which transforms
the coordinates of the quaternion with the 'tensor' of the sinus and cosinus
as a rotation with the same quaternion. 
The electro-magnetic tensor has the same properties as Hamilton's quaternions.
The electro-magnetic tensor with electromagnetic fields  
$E = \frac{- \delta A}{\delta t} - \nabla\phi$ and 
$B = \nabla \times A $ 
with A the vector potential
$
{F}^{\mu\nu} = 
\begin{matrix}
0 & \frac{{-E}_{x}}{c} & \frac{{-E}_{y}}{c} & \frac{{-E}_{z}}{c} \\
\frac{{E}_{x}}{c} & 0 	& {-B}_{z} & {B}_{y} \\
\frac{{E}_{y}}{c} & {B}_{z} & 0 & {-B}_{x} \\
\frac{{E}_{z}}{c} & {-B}_{y} & {B}_{x} & 0
\end{matrix} 
$

$
{F}_{\mu\nu} = 
\begin{matrix}
0 & \frac{{E}_{x}}{c} & \frac{{E}_{y}}{c} & \frac{{E}_{z}}{c} \\
\frac{{-E}_{x}}{c} & 0 	& {-B}_{z} & {B}_{y} \\
\frac{{-E}_{y}}{c} & {B}_{z} & 0 & {-B}_{x} \\
\frac{{-E}_{z}}{c} & {-B}_{y} & {B}_{x} & 0
\end{matrix} 
$
%FIXME dual quaternions and octonions
%FIXME quaternions differentiables into hamiltonian mechanics for interpolation on manifolds with tensor metric etc.
%FIXME pseudo-Riemannian manifolds
%FIXME Lagrangian tensor differentiable eqs
The Hamiltonian is the Legendre transform of the Lagrangian : 
$H({q}_{j},{p}_{j},t) = {\Sigma}_{i}{q}_{i}^{.}{p}_{i} - L({q}_{j},{q}_{j}^{.},t)$. This shows time dependance again.

\begin{figure}[h!]
\caption{Tensor reference, lightray as a twistor \cite{bookpenrose1} }
\includegraphics{tensor.eps} 
\end{figure}

\subsubsection{\large quaternion derived group theory}

The quaternion group ${Q}_{8}$ can be transformed with morphisms to other 
groups by $\oplus$ and $\otimes$ operators and tensor groups. 
%FIXME The rotation matrix derivedout of Hamilton's complex analysis' quaternion vector is an isomorphism to the matrix group with as many dimensions as there are complex numbers i,j and k.
${Q}_{8}$ is a linear group over field K with n finite 
dimensionality. The group is anti-symmetric. 

Lorentz groups are an extension to quaternion groups with respect to 'time'
dependancy where there is vector with x,y,z values for the definition
of a quaternion. The Lorentz group operates in Minkowski space time vector
spaces with complex tensors (the Electro-Magnetic tensor.) The Lorentz
function extends Maxwell's equation of a EM field to time constraints as
induction occurs with time-changing magnetic fields : 
$\nabla \times B = {\mu}_{0}J + {\mu}_{0}{\epsilon}_{0}\frac{\delta E}{\delta t}$
The above is in vacuum, dielectrica using $\delta t$ have tensors which 
stress the EM fields.

By applying these EM stress tensors we have a real example of the multiplication
(product) of tensors : $F = {F}_{d} \otimes {F}_{em}$ where ${F}_{em}$ 
is right-handed. 

The Lorentz group in this rotates the tensor with vector fields in 4 dimensions.

These equations are already 
extended to $c$, the speed of light for a norm for V vector space of $F$.
%FIXME write out the tensor products described above in F, Fem, Fd
%FIXME Kronecker product ?
$
F = {F}_{em} x {F}_{d} =% x {F}_{rotation}  = 
\begin{matrix}
0 & \frac{{-E}_{x}}{c} & \frac{{-E}_{y}}{c} & \frac{{-E}_{z}}{c} \\
\frac{{E}_{x}}{c} & 0 	& {-B}_{z} & {B}_{y} \\
\frac{{E}_{y}}{c} & {B}_{z} & 0 & {-B}_{x} \\
\frac{{E}_{z}}{c} & {-B}_{y} & {B}_{x} & 0
\end{matrix} 
\times 
{F}_{d}
$



%\times
%\begin{matrix}
%{w}^{2}+{x}^{2}-{y}^{2}-{z}^{2} & -2xy-wz & 2xz+2wy & 2xz+2wy & 0 \\
%2xy+2wz & {w}^{2}-{x}^{2}+{y}^{2}-{z}^{2} & 2yz+2wx & 0 \\
%2xz+2wy & 2yz-2wx &  {w}^{2}-{x}^{2}-{y}^{2}+{z}^{2} & 0 \\
%0 & 0 & 0 & 1
%\end{matrix} 
%$

The quaternion rotation can be written as : 
$rotw = cos(\frac{\phi}{2})$
$rotx = axisx * sin(\frac{\phi}{2})$
$roty = axisy * sin(\frac{\phi}{2})$
$rotz = axisz * sin(\frac{\phi}{2})$
and give
$
\begin{matrix}
cos(\frac{\phi}{2}) \\
axisx * sin(\frac{\phi}{2}) \\
axisy * sin(\frac{\phi}{2}) \\
axisz * sin(\frac{\phi}{2})
\end{matrix}
$
and where $\frac{\phi}{2} = \theta$ and $axisx,y,z$ have been omitted we
get the following EM tensor (multiply) scaled by the quaternion rotation
matrix :
$
{F}_{qi} = 
\begin{matrix}
\frac{{-E}_{x}}{c} sin(\theta) - \frac{{-E}_{y}}{c} sin(\theta) - \frac{{-E}_{z}}{c} sin(\theta) \\
\frac{{E}_{x}}{c} cos(\theta) - {B}_{z} sin(\theta) + {B}_{y} sin(\theta) \\
\frac{{E}_{y}}{c} cos(\theta) + {B}_{z} sin(\theta) - {B}_{x} sin(\theta) \\
\frac{{E}_{z}}{c} cos(\theta) - {B}_{y} sin(\theta) + {B}_{x} sin(\theta) \\
\end{matrix}
$
To apply the EM tensor to a quaternion tensor we define 
$
\begin{matrix}

\begin{matrix}
1 & 0 \\
0 & 1
\end{matrix}
& 
\begin{matrix}
1 & 1 \\
1 & -1
\end{matrix} \\
\begin{matrix}
-1 & 1 \\
1 & 1
\end{matrix}
&
\begin{matrix}
0 & -1 \\
1 & 0 
\end{matrix}

\end{matrix}
$
as a quaternion 'unitary' tensor ${T}^{q}$ of a 2-dimensional vector space V 
which can again be scaled as the components are all a combination of 
eigenvectors of V.
${T}^{q}$ is clearly a multi-linear map where the tensor product 
${F}^{qn} = {F}_{q} \times {F}_{em}$ changes the EM tensor with a twist.
%FIXME 
The Pauli matrices are $2 \times 2$ complex matrices used in connection with 
isospin symmetries. The quaternion group ${Q}_{8}$ as a subgroup of the 
general linear group ${GL}_{2}(c)$, and as an aspect of the special linear 
group incorporates these matrices.
%FIXME spin, pin groups and spinors

Isomorphisms of the spin group are things which relate to.
Spin(1),Spin(2),Spin(3),Spin(4),Spin(5),Spin(6), e.g. $Spin(4) = Sp(1) x Sp(1)$
is a product of simplectic groups, $n \times n$ quaternionic matrices which
preserve the usual inner product on ${H}^{n}$. 
As a research topic the changes in group elements
related to group operators yield interesting algebras. 
Interpolation with complex groups is of topological decency.
%FIXME homotopy cohomotopy and algebraic topology, says it all 
By mapping a tensor as a determinant or linear combination we get a surface
which is interpolated if the tensor does work. The map can be a kind of
inner product, (time) series, Riemannian metric and so on.

Out of the quaternion tensor field (derivatives and gradients of ${F}_{qn}$
follows that the quaternion group is Hamiltonian and non-abelian 
(non-commutative.) 
A quaternion is constant with angle == 45 degrees, sqrt(2)/2 radians, 
this is an imaginary number in i,j,k : $\frac{x -cos(\phi)}{sin(\phi)} = i$.
A tensor has rank 3*n and has 3 subdivisions of the axes on the unitary 
circle, each subdivision is 45 degrees. %FIXME 120 degrees premutes ijk
See figure for change in divergence through a surface which is 0.
$\frac{-cos(\phi)}{sin(\phi)}$
\begin{figure}[h!]
\caption{ $\frac{cos(\phi)}{sin(\phi)}$ The divergence over the square surface is clearly 0. If we rotate the square we have a changing flux and $div B \neq 0$. } 
\includegraphics{i2.eps} 
\end{figure}

%FIXME better picture not approx
\begin{figure}[h!]
\caption{F vectors over $\phi \in [-PI/2,+PI/2]$ with axisx = 15, axisy = 5, axisz = 5 and E = (1,0,0) and B = (0,10), Imagine this as a solenoid where the tensor gives energy with changes in flux through the solenoid. } 
\includegraphics{tensorquat2.eps} 
\end{figure}
\begin{figure}[h!]
\caption{sin(x)-sin(y) } 
\includegraphics{tensorquat.eps} 
\end{figure}



\subsubsection{\large quaternion, tensors and time series}
The Clifford algebra Cl(V,Q) produces a graded algebra with Tensor algebra T(V)
where ${F}^{0} \subset {F}^{1} \subset ... \subset {F}^{k}$ contains sums of tensors with $rank <= k$.
${Gr}_{F}Cl(V,Q) = {\bigoplus}_{k} {F}^{k} / {F}^{k-1}$.%FIXME write out calcs

Writing out the tensor divisions one can see that the EM tensor is divided 
by c, the speed of light. The $\nabla \times A$, curl is summed by definition
of the graded algebra and becomes a division of magnetic flux, as the tensors
deliver work which gets smaller by dividing the tensors. The higher the basis
count the lesser the ranks, the tensor sum filters less.

The ${F}^{q}$ tensor can also be productized with an external Hamiltonian tensor
which defines the change of the EM-q tensor through space - with fields on
vector space V. It has rank $2n \times 2n$ equating the rank of the quaternion 
group tensor. The Lorentz group tensor calculates the change of time and can
release work by interpolation, as $t \rightarrow {t}^{2}-{x}^{2}-{y}^{2}-{z}^{2}$ is preserved and -1 coefficients are e.g. Hamilton's ${i}^{2} = -1$.
The Lorentz group has an isomorphism with rank $2n \times 2n$ rank tensors of 
the quaternion group and $2 \times 2$ for the Lorentz group tensor.
The Hamiltonian tensor above is $
\begin{matrix}

\begin{matrix}
1 & 0 \\
0 & 1
\end{matrix}
& 
\begin{matrix}
1 & 1 \\
1 & -1
\end{matrix} \\
\begin{matrix}
-1 & 1 \\
1 & 1
\end{matrix}
&
\begin{matrix}
0 & -1 \\
1 & 0 
\end{matrix}

\end{matrix}
$

%FIXME Cybernetics - Norbert Wiener - series

${F}^{k} / {F}^{k-1}$ is a series divided by a series where the quadratic form
$Q(V)$ is a tensor metric of an algebra and and the division of tensors is 
summed to give a graded algebra.

The full tensor mechanism can be seen as a twistor (see figure) \cite{audiopenrose} operating on 
spin 1 particles with relation to the spinor group Spin(1). Interpolation
is done under different angles on this manifold.



\subsubsection{\large quaternions, relativity and particles }

Relativity came out of Lorentz transformations on the EM tensor with the Maxwell-
Lorentz equation.

Now we will dive into physical theories of (quaternion-related) manifolds to particle theory.

The Dirac equation shows an imaginary time derivative to be a sum of tensors :
$(c \alpha \cdot p + \beta m {c}^{2}) \psi = i \hbar \frac{\delta \psi(x,t)}{\delta t}$.
The Dirac equation can be seen as a light source which can not be interpolated.
A twistor on the light ray clarifies this, in Minkowski space (x,y,z,t) the 
solutions to the twistor equation are 
$\Omega(x) = {\omega}^{A} - i{x}^{AA'}{\pi}_{A'}$ where the latter part is the
imaginary part of the Dirac equation as ${x}^{AA'}$ is a point and ${\omega}^{A}$
and ${\pi}^{A'}$ are two constant Weyl spinors.%FIXME calc the Dirac eq
The spinors are related to the tensors on the left of the Dirac equation.
The graded algebra of the (Dirac's pure imaginary) quaternion tensor is again a 
filtration of the time derivatives of different angles $\psi$ as the spinors 
classify as a Clifford algebra. If $\psi$ and the tensors are non-zero, the 
tensors apply a force and thus work becomes a reality, the flux of the angle
through time delivers imaginary work. The tensors make the time twist 
relativistic. If all tensors are zero the system will be in equilibrium (cfr.
Shrodinger equation) and all energy will be constant.
${Z}^{\alpha} = ({\omega}^{A},{\pi}_{A'}$ is the definition of a twistor and
$\epsilon = \frac{1}{2}{Z}^{\alpha}{Z}_{\alpha}$ with ${Z}_{\alpha} = ({\pi}_{A'},{\omega}^{A'}$.

\subsubsection{\large Pauli Matrices }

%FIXME
Determinants of Pauli matrices can be imaginary or real, by the quaternion
interpolation you can create a field which can be interpolated.
You can interpolate tih these tensors on EM fields and other fields. 

The tensor can be of a quantum field also. This makes three solutions :
EM, common tensors and quantum mechanics.

You can see that light is by the ultra violet catastrophe electricity and
can be extended thus with quantum electrodynamics.

Feynman diagrams correlate the collisions of elementary particles where
for an electron and a positron a neutrino and antineutrino are generated
which obey the former Dirac equation for Weyl Spinors \cite{bookweyldirac}. Radiation
for Weyl Spinor particles can be of a functional field type. Functionals
are mappings as e.g. tensors. Integrals span the energy of this as a
Lagrangian for Field Loss and mechanical energy. Functionals of e.g.
Godel's theorem can exist or not, we can then relate the Godel theory
e.g. of series of functions
to limits of complex functions, $lim_{x -> 0}\frac{x + \delta x}{x}$ \cite{bookcomplexanalysiscain}
which has 2 solutions and so does not exist though our theory does
correlate the existence of a complex axes limit, one on the real part,
one on the imaginary axis. This can be called an anti-parallellogram
instead of the usual $a cos\phi + i sin\phi$. Godel's theorem does now 
not compensate for the non-existence of the limit unless we extend the
limit's definition to multiple solutions on imaginary axes.



%FIXME investigation of all field theories for FET, field theory electronics
%for GPUs, induction on these with interpol complex analysis

%FIXME try to find math writings of complex analysis, topology and 
% the matrices Pauli for OFl a screen with boson/photon spinor theory
% also twistor theory

Thus we could make a mechanical tensor FET, a pendulum for example (extrapolated) and EM with current and an quantum FET (positron and electron collider)
with wiping up neutrinos and antineutrinos. Complex analysis makes that
neutrinos are left handed and antineutrinos are righthanded.
%FIXME neutrino theory

Let us now concentrate more on twistor theory : the zero rest mass equation 
state that neutrinos and gauge bosons satisfy the former. In our quantum
FET the neutrinos have $\nabla^{A}_{A'} \phi^{AB...E} = 0$. Thus there
is zero spin and zero energy radiation except for the anti-neutrinos, 
which have half-integer spin.

The Levi-Civita connection has the following definition : 
\begin{itemize}
\item it preserves the metric $\nabla g = 0$
\item it is torsion-free, i.e. for any vector fields X and Y we have 
$\nabla_{X}Y - \nabla_{Y}X = [X,Y]$ where $[X,Y]$ is the Lie Bracket of the vector fields X and Y.
(This is the stress tensor of section 'Quaternion Derived Group Theory' in e.g. dielectrica, applying the EM tensors to real-world systems.)
\end{itemize}

$\phi$ has one index for the neutrino, two for the photon, four for the graviton.
For the photon, a gauge boson, the zero rest mass equation states the vanishing
of the divergence of the field strength tensor For the graviton, it gives
the Bianchi identity for a linearized Weyl spinor.\\
To clarify : the divergence, meaning the source or sink of the spinor field
$\phi$ drains all energy of the complex field (of spin ; of tensors of spin, spinors.)

%%FIXME
The Weyl spinor is a complex spinor based on Pauli matrices whereas the
Dirac spinor is one for quantum field theory. We need both in our next 
section as was stressed in tensor mechanics of the Weyl spinor above.

See also \cite{articlecliffordtwistor} for a description of the bosonic,
fermionic and Clifford algebra generalisation on twistors (you either have
elementary particles with spinors : fermions, bosons and the fraction of
tensors which relates to Clifford algebra, this fraction is a divergence
of the field as in optics with refraction and diffraction but with tensor mechanics.)

Diffraction is how light circumvents an obstacle. Refraction is how light 
bends its path when passing through a material. Geometrical optics make that
the light rays have the following equation : $\frac{sin \theta_{1}}{sin \theta_{2}} = n$.
This can be seen as a stress tensor described above for EM wave particles (light.)


In a Clifford algebra there is a universal property which is a propagation of 
a refraction, $f . i = g$, with a parallellogram for propagated fields e.g.
fields which when colliding generate a particle \cite{bookemperor} \cite{wikipedia-clifford-algebra}.


According to the spin-statistics theorem the particles spin is related
to the statistics it obeys \cite{wikipedia-spin-statistics-theorem}. The 
former cited theory holds for the particles we will discuss in the next section.

%FIXME see references of articlecliffordtwistor cite

The conclusion is that photons emmitted from a DVST/CRT break with refraction
and that spinors are applicative for these elementary particles. Fermions
are anti-symmetric in field theory and bosons (photons) are symmetric and
have integer spin \cite{wikipedia-gauge-bosons}.

The pixels on a screen emit these spinning photons as a DVST/CRT was developed
after 1929, when this spinor and field theories were invented. The interpolations of a laser or offscreen emmission bends light in ways described next, with
also some fermion (Fermi-Dirac statistics) particle theories for the 
Java-Ambienttalk system we developed diagonally. Refraction of light based
on pixels is what makes a computer screen a physical entity on the road
to e.g. 3D volumetric displays or QGP displays \cite{plasmamath} \cite{cgtutorial}.

%%%FIXME QGP uitbreiden met display
%%%FIXME ATalk code voor vanalles


\subsubsection{\large Elementary Particles - Bosons, Weyl Spinor particles, Neutrinos, fermions }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 	FIXME BOF -> better readability and material
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

See \cite{wikipedia-gauge-bosons} for an introduction on bosonic particles.
I will now do a BOF (Birds of Feather) to alleviate some general principles
and corresponding applicatives.\\

The purpose is to determine if OpenGL or GPUs can be structured using future
elemenatry particle theory in an elegant manner.


%% FIXME include thesis.10.txt

%% FIXME Plucker coords
The Plucker coordinates relate to displacement and moment of 2 vectors.
Twistor theory relates complex twistor space e.g. with Pauli matrices with
space of light rays in space-time.
\\
We will now introduce elementary particles using spinors.\\
\\
Gauge bosons are one of the following :
\begin{itemize}
\item photons
\item W and Z bosons
\item gluons
\end{itemize}

For applications and introductive material see for example Quark Gluon Plasmas \cite{plasmamath}.

The Lorentz group is a linear space transformation Lie group with homeomorphisms in the linear space itself ($O(1,3)$.)
There are tensor and vector fields applicable. Vector fields in complex
space drain or source with Weyl spinors where the energy goes to zero.
The Lorentz transformation attracts as it is a root, thus space-time can
be curved, this is 4 dimensional and named Minkowski space.

In the Standard Model, the Higgs field is a $SU(2)$ doublet, a complex
spinor with four real components (or equivalently two complex components.)

A Higgs field is a virtual particle, boson interaction mechanism. According
to Goldstone's theorem, these bosons should be massless and obey relativistic
quantum field theories (Lorentz, Complex and/or Quanta.)

Spinors exist in complex vector space with rotation groups.

The path integral for photons can be described by the Lorentz Gauge, which is 
zero.\\
Another example is using the Lorentz transformation as a quantum computational
system. Quantum Lorentz encryption can be used to develop a cryptofier
or code breaker by jumping between quantum states and using 
GA (Genetic Algorithms) properties of the Lorentz group. Quantum encryption
uses photon polarization as discussed above (see former complex analysis 
theory e.g. an imaginary field interpolation can be become real.)

%% FIXME try to produce Quantum Group Theory, so non-repetitive groups

Fibonnaci groups for example also uses a row of functions which can be complexified.
\\
Hopfield ANNs (Artificial Neural Networks) are self-reflective as are spins e.g.
a spinor $\frac{1}{2}$. Self-reflection with function (activation.)
\\
A chaotic system or dynamical system introduces fractals e.g. using the above
pointers. L-systems (Lindemayer systems, not Landau systems) are self-reflective. This means that they can be used in group theory.
Perturbation theory gives in a bias for an ANN, a random or constant factor,
which can be related to the zero mass equation.
\\
Banach spaces source or drain with vector or above fields.
Banach spaces can give assembly language functions, loops and labels together
with operators and operands, again use functional analysis. These become
e.g. Lie algebras of function space (eternal loops/L-systems.)
\\
CFGs (Context Free Grammars) within Banach space can be Turing-complete (Haskell, Gopher, Backus-Naur Forms, Python CFGs, ...)
Mips-III 4000 operands have 32 general purpose registers (also some ARM processors) which leads to group theory for processor mechanics.
\\
Polarized dark matter has unnoticed EM radiation. Gravitational radiation has
speed far below that of light. Weak gravitational lensing : matter bends light
passing beside it : refractive energies.
%% FIXME include some math for above paragraphs

Tubular L-systems or path integral within a tube (as Schrodinger's cat) makes
for Quantum Theory with a DVST/CRT (Cathode Ray Tube.)

Abraham-Minkowski controversy accounts for dielectrica, e.g. their EM stress
tensors. This contradiction states that as light travels through matter
it slows down or speeds up. Refraction is the observable in this case (See
also lensing above.)

Gauge bosons are the weak nuclear force, they are massive carriers of the force.
They are virtual particles.
Virtual particles can travel between 2 frames of reference (e.g. with
a Feynmann diagram), this is called Lorentz covariance and is related to
Lorentz symmetry.)


\subsubsection{\large Quantum Chromodynamics display technology}

As described in \cite{plasmamath} \cite{wikipedia-quantum-chromodynamics}
 the interpolation of quarks using gluons
and hadrons have color charge which can be put onto a screen. If one should
fire anit-neutrinos on a QGP (Quark Gluon Plasma) it changes its color.
This is achieved by using 3 quark colors as persent in an anti-neutrino.\\

Anti-neutrino guns should be able to achieve color transmission on a QGP
display.\\

The sources or drains of color charge (as discussed above in section) through
the zero mass equation gives a Lagrangian (e.g. with Lorentz gauge condition.)
and makes sure the color disappears offscreen.\\

A QGP motor is a continuous source of energy as hadrons collide e.g. a neutron
emits color charge by collideing in the QGP's source or drain of energy.\\

Time-dependancy of spinor energy is symmetric except for the strong force
between quarks. 
%%%FIXME time-dependancy, Lorentz tranfo, time for quarks

These hadrons obey a simple principle : they emit color charge under a fraction
as in general geometry optics. One can bend the given off color with an angular
momentum against the quark features.

The Mikheyev-Smirnov-Wolfenstein effect is as light traveling through
a transparent material for neutrinos, anti-neutrinos are right-handed neutrinos
 whereas a neutron is a massive particle emitted by collision of a positron and
neutrino. It is clear that a graded algebra on a quadric forms itself within 
the QGP. This could be the lead for having a geometrical optic effect where
the anti-neutrinos scale the quarks to other energies. The Lagrangian of this
effect is a scalable functional which polarizes e.g. photons coming out of
the quarks. This makes for a production system of chromodynamics.

Positrons only have opposite charge of electrons though this plays a role in
color charge emmission. The tensor algebra of the Clifford algebra which is 
equal to the graded algebra on all quadrics of quark polarization (if we may
call it this way) intensify this theory. More on this can be held from 
\cite{wikipedia-standard-model}.\\


According to the standard model QCD has global symmetry which means that
color charges are Lorentz invariant in space-time. Wave-functions can alternate
as electric charge can. The fact that anti-neutrinos collide with QGP to give
interpolations on color means that spinors and their algebras are transformed
with all possible quadrics of e.g. a texture on screen. This flatness is achieved by all particles which contain quarks. It should be possible to make for
other elementary particles that colors can be emmitted. We will now go on
in a small discussion of this among other things.\\
%%%%FIXME particles discussion with color charge emmission

Foremost there exists a theory of neutrino oscillations (which includes 
anti-neutrinos) which makes for neutrino flavor change. The covariant
neutrinos become a series with SU group matrix which fysically
changes the spin of these particles.
\\
Quark decay can occur when particles decay. As their mass changes (as in
neutron - heavy particle emmission) the particle can switch quarks. This
alleviates for a color charge theory which is non-relative to the fact that
collisions between quarks (using e.g. gluons) and particles emit color.
 


FIXME to be continued...



\subsubsection{\large Quaternions and OpenGL }

Extrapolating the angles in OpenGL code makes for relatively good tensors during
tesselation of a texture mapped surface. These imaginary tensors deliver work
if the manifold of this surface gets tensorified with a normal calculation e.g.
for ray casting or ray tracing. 
It remains to be seen that twistors can operate on a screen for interpolating
a ray of light \cite{bookpenrose1}. In the 3D engine Java code there is a 
normalize procedure, which works as above, repeated here for convenience :

\begin{mylisting5}
\begin{verbatim}
public void normalize()
{
	float magnitude = array[0]*array[0]+array[1]*array[1]+array[2]*array[2]+array[3]*array[3];

	if (magnitude == 0)
		return;

	array[0] /= magnitude; 
	array[1] /= magnitude; 
	array[2] /= magnitude; 
	array[3] /= magnitude; 
}
\end{verbatim}
\end{mylisting5}

A spinor can be defined by a Pauli or Quaternion group matrix and with previous
results of $i = \frac{x-cos(\phi)}{sin(/phi)}$ there exists another interpolation
mechanism which can be written out as a rotation quaternion, the Java code 
herefor is repeated below for convenience :

\begin{mylisting6}
\begin{verbatim}

public Quaternion rotate(float angle, float xaxisx, float yaxisy, float zaxisz)
{
	return new Quaternion((float)Math.cos(angle/2),
						xaxisx*Math.sin(angle/2),
						yaxisy*Math.sin(angle/2),
						zaxisz*Math.sin(angle/2));	

}

\end{verbatim}
\end{mylisting6}

If we combine both code blocks above we get the spinor interpolation method 
described above.

\subsubsection{\large Fraction and Vertex Class Java code }
\begin{mylisting2}
\begin{verbatim}

class Vector3 
{

// A color can be added here if you wish 
protected int[] array = new int[3];
protected Fraction fraction = new Fraction(0f);

	class Fraction 
	{
		float f = 0f;
		Fraction(float ff)
		{
			f = ff;
		}
		
		public float getFloat()
		{
			return f;
		}
		public void setFloat(float ff)
		{
			f = ff;	
		}
	};

public Vector3(int xx, int yy, int zz)
{
	array[0] = xx;
	array[1] = yy;
	array[2] = zz;
}

public Vector3 add(int xx, int yy, int zz)
{
	array[0] += xx;
	array[1] += yy;
	array[2] += zz;

	return this;
}

public Vector3 add(Vector3 v)
{
	int vx = v.x() + array[0];
	int vy = v.y() + array[1];
	int vz = v.z() + array[2];
	return new Vector3(vx,vy,vz);
}
public int x() 
{
	return array[0];
}

public int y() 
{
	return array[1];
}

public int z() 
{
	return array[2];
}

		

\end{verbatim}
\end{mylisting2}




\subsection{\large Discussion }

Vector spaces can transform the norm of a Quaternion and yield different
Quaternion transformations based on this norm e.g. you can use 
${||{w}^2+{x}^2+{y}^2+{z}^2||}^2$. 



\subsection{\large Code for testing Vector space transformation to Quaternion rotation, translation and transformation }
\begin{mylisting3}
\begin{verbatim}


FIXME SCHEME CODE IS NOT COMPLETE
%%%%%%%%%%% FIXME SCHEME CODE IS NOT COMPLETE

;; Copyright (C) Johan Ceuppens 2012
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 2 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

(load "quaternion.scm")

(define fruitloops 2000)
(define fruitw 2000)
(define fruitx 2000)
(define fruity 2000)
(define fruitz 2000)

(define (sqr x)
	(* x x))

(define v (make-vector3 x y z))

(define (norm1 w x y z)
	(sqr (sqr w)(sqr x)(sqr y)(sqr z))) 

;;test sample coords
(define *x 100)
(define *xn 1000)
(define *y 100)
(define *z 100)

(define (print-transformation q m)
	(let ((vn ((m 'mul) v)))
		(cond ((and (>= ((vn 'get-x)) *x)(<= ((vn 'get-x)) *xn))
			(display "hit")(display "x=")
					(display ((q 'get-x)))
					(display " y=")
					((q 'get-y))
					(display " z=")
					((q 'getz))
					(newline)))
	))
				
(do ((i 0 (+ i 1)))
	((i > fruitloops) (display "quitting...")(newline))
	(let ((q (make-quaternion (random fruitw)(random fruitx)(random fruity)(random fruitz))))
		(let ((m (q 'get-rotationmatrix)))
			(let ((n (norm1 ((q 'get-w))((q 'get-x))((q 'get-y))((q 'get-z)))))
				(set! q (make-quaternion (/ w n)
							(/ x n)
							(/ y n)
							(/ z n))) 
 
				(print-transformation q m)	
		)))
	)

	
;; Copyright (C) Johan Ceuppens 2012
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 2 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.


(load "matrix.scm")

(define (make-quaternion ww xx yy zz)
	(let ((x xx)
		(y yy)
		(z zz)
		(w ww))

	(define (get-w)
		w)
	(define (get-x)
		x)
	(define (get-y)
		y)
	(define (get-z)
		z)

	(define (get-conjugate)
		(make-quaternion w -x -y -z))	

	(define (mulitply q2)
		(let ((x2 ((q2 'x)))
			(y2 ((q2 'y)))
			(z2 ((q2 'z)))
			(w2 ((q2 'w))))

		(make-quaternion (- (- (- (* w w2) (* x x2)) (* y y2)) (* z z2))
				(- (+ (* w x2) (* x w2)(* y z2)) (* z y2))
				(+ (- (* w y2)(* x z2))(* y w2)(* z x2))
				(+ (- (+ (* w z2)(* x y2))(* y x2))(* z w2)))
			))
		))

	(define (sqr x)
		(* x x))

	(define (normalise)
		(sqrt (sqr w) (sqr x) (sqr y) (sqr z))) 

	(define (rotationmatrix)
		(make-matrix (+ (sqr x) (sqr y) (sqr z) (sqr w))
				(- (* 2 x y)(* 2 w z))  
				(+ (* 2 x z)(* 2 w y))
				(+ (* 2 x y)(* 2 w z))
				(+ (- (sqr w)(sqr x))(- (sqr y)(sqr z)))  
				(+ (* 2 y z)(* 2 w x))
				(- (* 2 x z)(* 2 w y))  
				(- (* 2 y z)(* 2 w x))  
				(+ (- (- (sqr w)(sqr x))(sqr y)) (sqr z)))) 

	(lambda (msg)
	(cond ((eq msg 'x)get-x)
		((eq msg 'w) get-w)
		((eq msg 'x) get-x)
		((eq msg 'y) get-y)
		((eq msg 'z) get-z)
		((eq msg 'conjugate) get-conjugate)
		((eq msg 'normalise) normalise)
		((eq msg 'get-rotationmatrix)rotationmatrix)	
		(else (display "make-quaternion : message not understood ")
			(display msg)(newline))))

))


\end{verbatim}
\end{mylisting3}


\section{\large Matrix Theory }

% FIXME Kronecker product <-> tensor product

\subsection{\large Basics }
\subsection{\large Discussion }

ring theory
energy of Quaternion martices
Pauli Matrices.

\section{\large General Discussion }



\section{\large Java code}

We chose Java and Java's AWT for portability reasons and in this timeframe for
wearable and pocket computing devices. 
%FIXME An iOS version might follow.

\begin{mylisting}
\begin{verbatim}

package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class BoundingBox 
{
protected int mapx, mapy, mapw, maph;

public BoundingBox(int startx, int starty, int startw, int starth)
{
	mapx = startx;
	mapy = starty;
	mapw = startw;
	maph = starth;
}

public int getx()
{
	return mapx;
}

public int gety()
{
	return mapy;
}

public int getw()
{
	return mapw;
}

public int geth()
{
	return maph;
}

public void moveleft() 
{
	mapx--;
}
public void moveright() 
{
	mapx++;
}
public void moveup() 
{
	mapy--;
}
public void movedown() 
{
	mapy++;
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Camera 
{

private Vector3 pos;
private Quaternion rotq = new Quaternion(1,0f,0f,0f);
private Matrix rotmatrix = rotq.getRotationMatrix();

public Camera()
{
	pos = new Vector3(0f,0f,0f);
}

public Camera(float ww, float xx, float yy, float zz)
{
	rotq = new Quaternion(ww,xx,yy,zz);
	rotmatrix = rotq.getRotationMatrix();
	pos = new Vector3(0f,0f,0f);

}	

public void movex(float dx)
{
	pos.add(rotmatrix.mul(new Vector3(dx,0f,0f)));
}

public void movey(float dy)
{
	pos.add(0f,-dy,0f);
}

public void movez(float dz)
{
	pos.add(rotmatrix.mul(new Vector3(0f,0f,-dz)));
}

public void rotatex(float dx)
{
	Quaternion nrot = new Quaternion((float)(dx*Math.PI/180),1f,0f,0f);
	rotmatrix = rotmatrix.mul(nrot.getRotationMatrix());

} 

public void rotatey(float dy)
{
	Quaternion nrot = new Quaternion((float)(dy*Math.PI/180),0f,1f,0f);
	rotmatrix = nrot.getRotationMatrix().mul(rotmatrix);
} 


public float x()
{
	return pos.x();
}

public float y()
{
	return pos.y();
}

public float z()
{
	return pos.z();
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

import javax.swing.JFrame;


public class Engine3D extends JFrame
{

  public Engine3D()
  {
    getContentPane().add(new Game());
    setTitle("3D");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(320, 200);
    setLocationRelativeTo(null);
    setVisible(true);
  }

  public static void main(String[] args) {
      new Engine3D();
  }
}
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.*;
import javax.swing.*;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GraphicsEnvironment;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.imageio.ImageIO;

import java.util.*;
import java.util.Random;
import java.awt.image.*;
import java.awt.image.BufferedImage;

public class Game extends JPanel implements ActionListener {
private String fileprefix = "./pics/";
private String musicfileprefix = "./music/";
private int SCREENWIDTH = 320;
private int SCREENHEIGHT = 200;
//private Texturef tex = new Texturef("door-48x48-1.png");
private Sphere sphere = new Sphere(100.0f,20);
private Translatef translatef = new Translatef(0,0,0);
private Camera cam = new Camera();

public Game() {
	
	Timer timer;

        addKeyListener(new TAdapter());
        setFocusable(true);
	
        setBackground(Color.white);
        setDoubleBuffered(true);

        timer = new Timer(40, this);
        timer.start();

	loadlevel1();

    }

    public void addNotify() {
        super.addNotify();
        GameInit();
    }

    public void loadlevel1()
    {
    }

    public void loadlevel2()
    {
    }

    public void GameInit() {
        LevelInit();
    }


    public void LevelInit() {

    }

/*
 * Collision detection code
 */
/****
   public boolean DoGatewayCollision()
    {
	for (int i = 0; i < gateways.size(); i++) {
		Object o = gateways.get(i);
		Gateway bo = (Gateway)o;
		if (collision(player.getx()-map.getx(),player.gety()-map.gety(),player.getw(),player.geth(),bo.getx(),bo.gety(),bo.getw(),bo.geth())) {

			currentgateway = bo;

			return true;
		}
	}
	return false;
    }	
*****/

/*
 * Drawing
 */ 
/*****    public void DrawGateways(Graphics2D g2d)
    {
	for (int i = 0; i < gateways.size(); i++) {
		Object o = gateways.get(i);
		Gateway bo = (Gateway)o;
		g2d.drawImage(bo.getImage(), bo.getx()+map.getx(), bo.gety()+map.gety(), this);
	}
    }	
*****/
	
    public void paint(Graphics g)
    {
      Graphics2D g2d = (Graphics2D) g;
	g2d.setColor(Color.black);
      g2d.fillRect(0, 0, 320, 200);
      g2d.setColor(Color.red);

	for (int i = 0; i < sphere.size(); i++) {

		Vector3 v = sphere.getVertex(i);
		//v = new Quaternion(2f,2f,2f,2f).rotateVector(v);	

		cam.movey(2f);
		//cam.rotatex(0.2f);
		v = new Vector3(cam.x(),cam.y(),cam.z());
      		g2d.fillRect((int)v.x()+(int)sphere.x(),(int)v.y()+(int)sphere.y(),1,1);
			

	} 

      //g2d.drawImage(tex.getImage(),null,null);
      Toolkit.getDefaultToolkit().sync();
      g.dispose();

    }

    class TAdapter extends KeyAdapter {
        public void keyReleased(KeyEvent e) {
	} 
      
        public void keyPressed(KeyEvent e) {

          int key = e.getKeyCode();

	   	if (key == KeyEvent.VK_LEFT) {
			sphere.setx(sphere.x()-1f);
			repaint();	
		}
	   	if (key == KeyEvent.VK_RIGHT) {
			sphere.setx(sphere.x()+1f);
			repaint();	
	   	}
	   	if (key == KeyEvent.VK_UP) {
			sphere.sety(sphere.y()-1f);
			repaint();	
	   	}
	   	if (key == KeyEvent.VK_DOWN) {
			sphere.sety(sphere.y()+1f);
			repaint();	
		}	
	   	if (key == KeyEvent.VK_X) {
	   	}
	   	if (key == KeyEvent.VK_Z) {//go back to history of talkmodes
	   	}
		if (key == KeyEvent.VK_ESCAPE) {
	   		System.exit(99);
		}
	}
    }

    public void actionPerformed(ActionEvent e) {
        repaint();  
    }

}
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Matrix 
{

protected float[] array = new float[9]; 

public Matrix(float xx1, float yy1, float zz1, float xx2, float yy2, float zz2, float xx3, float yy3, float zz3)
{

	array[0] = xx1;	
	array[1] = yy1;	
	array[2] = zz1;	
	array[3] = xx2;	
	array[4] = yy2;	
	array[5] = zz2;	
	array[6] = xx3;	
	array[7] = yy3;	
	array[8] = zz3;	

}

public Matrix mul(Matrix m)
{
	float[] a = m.array();
	float vx1 = a[0]*array[0]+a[1]*array[1]+a[2]*array[2];
	float vy1 = a[0]*array[3]+a[1]*array[4]+a[2]*array[5];
	float vz1 = a[0]*array[6]+a[1]*array[7]+a[2]*array[8];
	float vx2 = a[3]*array[0]+a[4]*array[1]+a[5]*array[2];
	float vy2 = a[3]*array[3]+a[4]*array[4]+a[5]*array[5];
	float vz2 = a[3]*array[6]+a[4]*array[7]+a[5]*array[8];
	float vx3 = a[6]*array[0]+a[7]*array[1]+a[8]*array[2];
	float vy3 = a[6]*array[3]+a[7]*array[4]+a[8]*array[5];
	float vz3 = a[6]*array[6]+a[7]*array[7]+a[8]*array[8];

	return new Matrix(vx1,vy1,vz1,vx2,vy2,vz2,vx3,vy3,vz3);
}

public Vector mul(Vector v)
{
	float vx = v.x()*array[0]+v.y()*array[1]+v.z()*array[2];
	float vy = v.x()*array[3]+v.y()*array[4]+v.z()*array[5];
	float vz = v.x()*array[6]+v.y()*array[7]+v.z()*array[8];

	return new Vector(vx,vy,vz);
}

public Vector3 mul(Vector3 v)
{
	float vx = v.x()*array[0]+v.y()*array[1]+v.z()*array[2];
	float vy = v.x()*array[3]+v.y()*array[4]+v.z()*array[5];
	float vz = v.x()*array[6]+v.y()*array[7]+v.z()*array[8];

	return new Vector3(vx,vy,vz);
}

public Vector3 mul2(Vector3 v)
{
	float vx = v.x()*array[0]+v.y()*array[1]+v.z()*array[2];
	float vy = v.x()*array[3]+v.y()*array[4]+v.z()*array[5];
	float vz = v.x()*array[6]+v.y()*array[7]+v.z()*array[8];

	return new Vector3(vx,vy,vz);
}


public float[] array()
{
	return array;
} 


};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class ModelNativeBase 
{
private VerticesList vertices = new VerticesList();
private int size = 0;
public ModelNativeBase()
{

	
}

public void addVertex(float xx, float yy, float zz)
{
	vertices.addVertex(new Vector3(xx,yy,zz));
}

public Vector3 getVertex(int n)
{
	Object o = vertices.getVertex(n);//FIXME
	return (Vector3)o;
}

public int size()
{
	size = vertices.size();
	return size;
}
};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class ModelNative extends ModelNativeBase 
{
protected float x = 0f, y = 0f, z = 0f;

public ModelNative()
{

	
}

public void setx(float xx)
{
	x = xx;	
}

public void sety(float yy)
{
	y = yy;	
}

public void setz(float zz)
{
	z = zz;	
}

public float x()
{
	return x;
}

public float y()
{
	return y;
}

public float z()
{
	return z;
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

/*
 * representation : w+ix+jy+kz
 */
class Quaternion 
{

protected float[] array = new float[4];

public Quaternion(float ww, float xx, float yy, float zz)
{
	array[0] = ww;
	array[1] = xx;
	array[2] = yy;
	array[3] = zz;
}

public Quaternion conjugate()
{
	return new Quaternion(array[0],-array[1],-array[2],-array[3]);
}

public Quaternion add(float ww, float xx, float yy, float zz)
{
	array[0] += ww;
	array[1] += xx;
	array[2] += yy;
	array[3] += zz;

	return this;
}

//this q multiplied by q2
public Quaternion mul(Quaternion q2)
{

	return new Quaternion(array[0]*q2.w()-array[1]*q2.x()-array[2]*q2.y()-array[3]*q2.z(),
			array[0]*q2.x()+array[1]*q2.w()+array[2]*q2.z()-array[3]*q2.y(),
			array[0]*q2.y()-array[1]*q2.z()+array[2]*q2.w()+array[3]*q2.x(),
			array[0]*q2.z()+array[1]*q2.y()-array[2]*q2.x()+array[3]*q2.w());


}

public Vector3 rotateVector(Vector3 v)
{
	Vector3 vn = new Vector3(v.x(),v.y(),v.z());
	vn.normalize();


	Quaternion vq = new Quaternion(0f,vn.x(),vn.y(),vn.z());
	Quaternion rq = vq.mul(conjugate());
	rq = mul(rq);

	return new Vector3(rq.x(),rq.y(),rq.z());	
}

public Quaternion rotate(float angle, float xaxisx, float yaxisy, float zaxisz)
{
	float s = (float)Math.sin(angle/2);
	return new Quaternion((float)Math.cos(angle/2),xaxisx*s,
						yaxisy*s,
						zaxisz*s);	

}

public Matrix getRotationMatrix()
{
//NOTE norm is x*x+y*y+z*z+w*w 
	return new Matrix(array[0]*array[0]+array[1]*array[1]-array[2]*array[2]-array[3]*array[3],
			2*array[1]*array[2]-2*array[0]*array[3],
			2*array[1]*array[3]-2*array[0]*array[2],
			2*array[1]*array[2]+2*array[0]*array[3],
			array[0]*array[0]-array[1]*array[1]+array[2]*array[2]-array[3]*array[3],
			2*array[1]*array[3]+2*array[0]*array[1],
			2*array[1]*array[3]-2*array[0]*array[2],
			2*array[1]*array[3]-2*array[0]*array[1],
			array[0]*array[0]-array[1]*array[1]-array[2]*array[2]+array[3]*array[3]);

}

//You can normalize a q to a unti q but the product will then be again a unit q
public void normalize()
{
	float magnitude = array[0]*array[0]+array[1]*array[1]+array[2]*array[2]+array[3]*array[3];

	if (magnitude == 0)
		return;

	array[0] /= magnitude; 
	array[1] /= magnitude; 
	array[2] /= magnitude; 
	array[3] /= magnitude; 
}


public float w() 
{
	return array[0];
}

public float x() 
{
	return array[1];
}

public float y() 
{
	return array[2];
}

public float z() 
{
	return array[3];
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Rotatef
{
protected float theta = 0.0f;
private Matrix matrotx = new Matrix(1f,0f,0f,
				0f,(float)Math.cos(theta),(float)-Math.sin(theta),
				0f,(float)Math.sin(theta),(float)Math.cos(theta));
private Matrix matroty = new Matrix((float)Math.cos(theta),(float)-Math.sin(theta),0f,
				(float)Math.sin(theta),(float)Math.cos(theta),0f,
				0f,0f,1f);	
private Matrix matrotz = new Matrix((float)Math.cos(theta),0f,(float)Math.sin(theta),
				0f,1f,0f,
				(float)-Math.sin(theta),0f,(float)Math.cos(theta));
public Rotatef()
{

}



};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Scalef
{
private Matrix mattrans = null; 

public Scalef(float xx, float yy, float zz)
{
	mattrans = new Matrix(xx,0f,0f,
				0f,yy,0f,
				0f,0f,zz);
}

public Vector3 f(float xx, float yy, float zz, Vector3 v)
{
	mattrans = new Matrix(xx,0f,0f,
				0f,yy,0f,
				0f,0f,zz);
	return mattrans.mul2(v);
}

public Vector3 f(Vector3 v)
{
	return mattrans.mul2(v);
}

public Vector f(float xx, float yy, float zz, Vector v)
{
	mattrans = new Matrix(xx,0f,0f,
				0f,yy,0f,
				0f,0f,zz);
	return mattrans.mul(v);
}

public Vector f(Vector v)
{
	return mattrans.mul(v);
}




};
package game;
/*
 *	SimpleMidiPlayer.java
 *
 *	This file is part of jsresources.org
 */

/*
 * Copyright (c) 1999 - 2001 by Matthias Pfisterer
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
|<---            this code is formatted to fit into 80 columns             --->|
*/

import java.io.File;
import java.io.IOException;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;




/**	<titleabbrev>SimpleMidiPlayer</titleabbrev>
	<title>Playing a MIDI file (easy)</title>

	<formalpara><title>Purpose</title>
	<para>Plays a single MIDI file.</para></formalpara>

	<formalpara><title>Usage</title>
	<para>
	<cmdsynopsis>
	<command>java SimpleMidiPlayer</command>
	<arg choice="plain"><replaceable>midifile</replaceable></arg>
	</cmdsynopsis>
	</para></formalpara>

	<formalpara><title>Parameters</title>
	<variablelist>
	<varlistentry>
	<term><option><replaceable>midifile</replaceable></option></term>
	<listitem><para>the name of the MIDI file that should be
	played</para></listitem>
	</varlistentry>
	</variablelist>
	</formalpara>

	<formalpara><title>Bugs, limitations</title>

	<para>This program always uses the default Sequencer and the default
	Synthesizer to play on. For using non-default sequencers,
	synthesizers or to play on an external MIDI port, see
	<olink targetdoc="MidiPlayer"
	targetptr="MidiPlayer">MidiPlayer</olink>.</para>
	</formalpara>

	<formalpara><title>Source code</title>
	<para>
	<ulink url="SimpleMidiPlayer.java.html">SimpleMidiPlayer.java</ulink>
	</para>
	</formalpara>

*/
public class SimpleMidiPlayer
{
	/*
	  These variables are not really intended to be static in a
	  meaning of (good) design. They are used by inner classes, so they
	  can't just be automatic variables. There were three possibilities:

	  a) make them instance variables and instantiate the object they
	  belong to. This is clean (and is how you should do it in a real
	  application), but would have made the example more complex.

	  b) make them automatic final variables inside main(). Design-wise,
	  this is better than static, but automatic final is something that
	  is still like some black magic to me.

	  c) make them static variables, as it is done here. This is quite bad
	  design, because if you have global variables, you can't easily do
	  the thing they are used for two times in concurrency without risking
	  indeterministic behaviour. However, it makes the example easy to
	  read.
	 */
	private static Sequencer	sm_sequencer = null;
	private static Synthesizer	sm_synthesizer = null;



	public static void playfile(String midifilename, int repeat)
	{
		/*
		 *	We check if there is no command-line argument at all
		 *	or the first one is '-h'.
		 *	If so, we display the usage message and
		 *	exit.
		 */

		String	strFilename = midifilename;
		File	midiFile = new File(strFilename);

		/*
		 *	We read in the MIDI file to a Sequence object.
		 *	This object is set at the Sequencer later.
		 */
		Sequence	sequence = null;
		try
		{
			sequence = MidiSystem.getSequence(midiFile);
		}
		catch (InvalidMidiDataException e)
		{
			/*
			 *	In case of an exception, we dump the exception
			 *	including the stack trace to the console.
			 *	Then, we exit the program.
			 */
			//e.printStackTrace();
			//System.exit(1);
			return;
		}
		catch (IOException e)
		{
			/*
			 *	In case of an exception, we dump the exception
			 *	including the stack trace to the console.
			 *	Then, we exit the program.
			 */
			//e.printStackTrace();
			//System.exit(1);
			return;
		}

		/*
		 *	Now, we need a Sequencer to play the sequence.
		 *	Here, we simply request the default sequencer.
		 */
		try
		{
			sm_sequencer = MidiSystem.getSequencer();
		}
		catch (MidiUnavailableException e)
		{
			//e.printStackTrace();
			//System.exit(1);
			return;
		}
		if (sm_sequencer == null)
		{
			//out("SimpleMidiPlayer.main(): can't get a Sequencer");
			//System.exit(1);
			return;
		}

		/*
		 *	There is a bug in the Sun jdk1.3/1.4.
		 *	It prevents correct termination of the VM.
		 *	So we have to exit ourselves.
		 *	To accomplish this, we register a Listener to the Sequencer.
		 *	It is called when there are "meta" events. Meta event
		 *	47 is end of track.
		 *
		 *	Thanks to Espen Riskedal for finding this trick.
		 */
		sm_sequencer.addMetaEventListener(new MetaEventListener()
			{
				public void meta(MetaMessage event)
				{
					if (event.getType() == 47)
					{
						sm_sequencer.close();
						if (sm_synthesizer != null)
						{
							sm_synthesizer.close();
						}
						//System.exit(0);
						return;
					}
				}
			});

		/*
		 *	The Sequencer is still a dead object.
		 *	We have to open() it to become live.
		 *	This is necessary to allocate some ressources in
		 *	the native part.
		 */
		try
		{
			sm_sequencer.open();
		}
		catch (MidiUnavailableException e)
		{
			//e.printStackTrace();
			//System.exit(1);
			return;
		}

		/*
		 *	Next step is to tell the Sequencer which
		 *	Sequence it has to play. In this case, we
		 *	set it as the Sequence object created above.
		 */
		try
		{
			sm_sequencer.setSequence(sequence);
		}
		catch (InvalidMidiDataException e)
		{
			//e.printStackTrace();
			//System.exit(1);
			return;
		}

		/*
		 *	Now, we set up the destinations the Sequence should be
		 *	played on. Here, we try to use the default
		 *	synthesizer. With some Java Sound implementations
		 *	(Sun jdk1.3/1.4 and others derived from this codebase),
		 *	the default sequencer and the default synthesizer
		 *	are combined in one object. We test for this
		 *	condition, and if it's true, nothing more has to
		 *	be done. With other implementations (namely Tritonus),
		 *	sequencers and synthesizers are always seperate
		 *	objects. In this case, we have to set up a link
		 *	between the two objects manually.
		 *
		 *	By the way, you should never rely on sequencers
		 *	being synthesizers, too; this is a highly non-
		 *	portable programming style. You should be able to
		 *	rely on the other case working. Alas, it is only
		 *	partly true for the Sun jdk1.3/1.4.
		 */
		if (! (sm_sequencer instanceof Synthesizer))
		{
			/*
			 *	We try to get the default synthesizer, open()
			 *	it and chain it to the sequencer with a
			 *	Transmitter-Receiver pair.
			 */
			try
			{
				sm_synthesizer = MidiSystem.getSynthesizer();
				sm_synthesizer.open();
				Receiver	synthReceiver = sm_synthesizer.getReceiver();
				Transmitter	seqTransmitter = sm_sequencer.getTransmitter();
				seqTransmitter.setReceiver(synthReceiver);
			}
			catch (MidiUnavailableException e)
			{
				e.printStackTrace();
			}
		}

		/*
		 *	Now, we can start over.
		 */
		sm_sequencer.start();

		if (repeat-- <= 0)
			return;
		playfile(midifilename, repeat);
	}



	private static void printUsageAndExit()
	{
		//out("SimpleMidiPlayer: usage:");
		//out("\tjava SimpleMidiPlayer <midifile>");
		//System.exit(1);
		return;
	}



	private static void out(String strMessage)
	{
		//System.out.println(strMessage);
	}
}



/*** SimpleMidiPlayer.java ***/
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Sphere extends ModelNative 
{
private float radius = 0f;
private float x = 0f,y = 0f, z = 0f;

public Sphere(float r, int pieces)
{
	radius = r;
	generatesphere(r,pieces);
}

public void generatesphere(float radius, int pieces)
{
                int meridians = 4*pieces;
                int parallels = 4*pieces;

                for (float theta = 0; theta < Math.PI; theta += Math.PI/meridians) {
                        for (float phi = 0; phi < 2*Math.PI; phi += 2*Math.PI/parallels) {

                                addVertex((float)(x+Math.cos(theta)*Math.sin(phi)*radius),
                                          (float)(y+Math.sin(theta)*Math.sin(phi)*radius),
                                          (float)(z+Math.cos(phi)*radius));
                        }      
                }
}

};
package game;
/*
Copyright (C) <year> <name of author>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.*;

class StateImageLibrary
{

private LinkedList images = new LinkedList();//FIXME static array size
String prefix = "./pics/";

private int index;
private int max;

public StateImageLibrary()
{
	index = 0;
	max = 0;
}
public void addImage(String filename)
{
      Object img2 = new ImageIcon(prefix+filename).getImage();
      Image img = (Image)img2;
      images.add(img);
      max += 1;     	
}
public Image getImage()
{
      if (index >= max)
	index = 0;
      Object img = images.get(index++);
      return (Image)img;
}
public Image getImage(int idx)
{
      if (idx >= max)
	idx = 0;
      Object img = images.get(idx);
      return (Image)img;
}

public int getmax()
{
	return max;
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.imageio.ImageIO;
import java.awt.Toolkit;
import java.awt.color.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.awt.image.*;
import java.util.*;
import java.io.*;
import java.nio.*;

class Texturef
{
private String prefix = "./pics/";
private BufferedImage bufferedImage;
private ByteBuffer bb;
private int w,h;
public Texturef(String imagefilename)
{
	try {
		bufferedImage = ImageIO.read(new File(prefix+imagefilename));
	} catch (IOException e) {}


	w = bufferedImage.getWidth();
	h = bufferedImage.getHeight();
	toByteBuffer();

	fade();

	toImage();
}

public BufferedImage getImage()
{
	return bufferedImage;
}

public void toByteBuffer()
{

BufferedImage imgImg;
WritableRaster raster;
	raster =
        Raster.createInterleavedRaster (DataBuffer.TYPE_BYTE,
                                                w,
                                                h,
                                                4,
                                                null);
        ComponentColorModel colorModel=
                                new ComponentColorModel (ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                                new int[] {8,8,8,8},
                                                true,
                                                false,
                                                ComponentColorModel.TRANSLUCENT,
                                                DataBuffer.TYPE_BYTE);
       imgImg =
       new BufferedImage (colorModel,
                          raster,
                          false,
                          null);

       DataBufferByte imgBuf =
       (DataBufferByte)raster.getDataBuffer();
	byte[] imgRGBA = imgBuf.getData();

        bb = ByteBuffer.wrap(imgRGBA);

		
}

public void toImage()
{
	//bufferedImage.read(bb);
}

public void fade()
{
	bb.position(0);
        for (int i = 0; i < w*h*4; i++) {
	        byte b = bb.get(i);
	        if (i%4!=3/* && fadingcounter != 0*/)  {
		        b-=2;
		        if (b < 0)
			        b = 0;
	        }
	        bb.put((byte)b);
        }
        bb.position(0);

}

/*
 * leftxoffset : top left of trapezoid
 * rightxoffset : right top of trapezoid
 * dx : towards left
 * dx2 towards right
 */
public void trapezoidtexturemap(ByteBuffer bb2, int capacity, int ww, int hh, int leftxoffset, int rightxoffset, float dx, float dx2)
{
                        int xoffset = 40;
                        int woffset = 40;
                        for (int j = 0; j < hh; j++) {
                        int pos1 = j*ww;
                        bb2.position(0);
			float l = 0;
                        for (int i = 0; i < ww; i++) {

                                if (i == 0) {
                                        bb2.position(pos1+leftxoffset-leftxoffset/w*j);
					for (int k = 0; k < leftxoffset; k++) {
						bb.put((byte)0);
					}
				}
                                else if (i >= rightxoffset) {
					for (int k = i; k < rightxoffset; k++) {
						bb.put((byte)0);
					}
                                        break;
				}

				leftxoffset -= dx;
				rightxoffset += dx2;
				leftxoffset = leftxoffset<0?0:leftxoffset;	
				rightxoffset = rightxoffset<0?0:rightxoffset;	
				l += i/(ww-leftxoffset-rightxoffset);
                                byte b = bb2.get((int)l+(int)j*ww);
                                bb.put((byte)b);

                        }
                        }
                        bb2.position(0);
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Translatef
{

private float x,y,z;

public Translatef(float xx, float yy, float zz)
{
	x = xx;
	y = yy;
	z = zz;
}

public Vector3 add(Vector3 v)
{
	return new Vector3(x,y,z).add(v.x(),v.y(),v.z());	
}

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Vector3 
{

protected float[] array = new float[3];//,color;

public Vector3(float xx, float yy, float zz)//, float cc)
{
	array[0] = xx;
	array[1] = yy;
	array[2] = zz;
	//color = cc;	
}

public Vector3 add(float xx, float yy, float zz)
{
	array[0] += xx;
	array[1] += yy;
	array[2] += zz;

	return this;
}

public Vector3 add(Vector3 v)
{
	float vx = v.x() + array[0];
	float vy = v.y() + array[1];
	float vz = v.z() + array[2];
	return new Vector3(vx,vy,vz);
}
public float x() 
{
	return array[0];
}

public float y() 
{
	return array[1];
}

public float z() 
{
	return array[2];
}

/******
public float c() 
{
	return color;
}

public float color() 
{
	return color;
}
*********/

public void normalize()
{
	float magnitude = array[0]*array[0]+array[1]*array[1]+array[2]*array[2];

	if (magnitude == 0)
		return;

	array[0] /= magnitude; 
	array[1] /= magnitude; 
	array[2] /= magnitude; 
}
};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class Vector 
{

protected float x,y,z;//,color;

public Vector(float xx, float yy, float zz)//, float cc)
{
	x = xx;
	y = yy;
	z = zz;
	//color = cc;	
}

public void add(float xx, float yy, float zz)
{
	x += xx;
	y += yy;
	z += zz;
}

public Vector add(Vector v)
{
	float vx = v.x() + x;
	float vy = v.y() + y;
	float vz = v.z() + z;
	return new Vector(vx,vy,vz);
}

public float x() 
{
	return x;
}

public float y() 
{
	return y;
}

public float z() 
{
	return z;
}

/******
public float c() 
{
	return color;
}

public float color() 
{
	return color;
}
*********/

};
package game;
/*
Copyright (C) 2012 Johan Ceuppens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.*;

class VerticesList
{
private int size = 0;
private LinkedList verticesList = new LinkedList();

public VerticesList()
{
}

public void addVertex(Vector3 v)
{
	verticesList.add(v);
}

public Vector3 getVertex(int idx)
{
	Object o = verticesList.get(idx);//FIXME
	return (Vector3)o;
}

public int size()
{
	size = verticesList.size();
	return size;
}
};
\end{verbatim}
\end{mylisting}


\section{\large Conclusion}


\bibliographystyle{plain}
\bibliography{part16} % refs.bib

\end{document}

%%

